package cn.maihe.elg.operation.supports.bank.cmb.tradingmanager;

import cn.hutool.core.util.RandomUtil;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.base.AR;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.AccountTrade;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.AccountTradeResumeInfo;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.AccountTradeToday;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.CashSubAccount;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.CommonRequestParam;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.ConfigDTO;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.NormalAccountTrade;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.NormalAccountTradeInfo;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.NormalAccountTradeQuery;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.NormalAccountTradeResumeInfo;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.pojo.NormalAccountTradeResumeQueryInfo;
import cn.maihe.elg.operation.supports.bank.cmb.tradingmanager.utils.CommonUtil;
import cn.maihe.elg.operation.utils.IdGenerate;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 招商银行现金管理工具类，详细文档查看
 * <a href="https://openbiz.cmbchina.com/developer/UI/Business/CloudDirectConnect/Public/DocumentCenter/DocDetail.aspx?bizkey=DCCT20201214145038074&fabizkey=1">招商文档</a>
 * <p>
 * 路径：现金管理 => 交易管家(记账)
 *
 * @version V1.0
 * @author: Sidon
 * @createTime: 2021-09-03 16:59
 * Copyright (C)2021-2021 福建省金柠网络科技有限公司. All rights reserved.
 */
@Slf4j
public class CashService {

    /**
     * [创建]招商银行[记账子单元](原来的虚拟子账号)
     * 交易管家(记账) > 2.新增记账子单元 NTDMAADD
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<JSONObject> subAccountCreate(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> body = new HashMap<>(2);
        Map<String, String> ntdmaaddx = new HashMap(8);
        //账号
        ntdmaaddx.put("accnbr", cashSubAccount.getBankAccount());
        //记账子单元编号 自定义记账子单元编号：非空 系统自动生成记账子单元编号：空
        ntdmaaddx.put("dmanbr", cashSubAccount.getSubAccount());
        //记账子单元名称
        ntdmaaddx.put("dmanam", cashSubAccount.getSubAccountName());
        //额度控制标志，Y：允许透支 N：不允许透支
        ntdmaaddx.put("ovrctl", "N");
        //退票处理方式，Y：退回原记账子单元 N：退回结算户
        ntdmaaddx.put("bcktyp", "Y");
        //业务参考号 客户保证唯一
        ntdmaaddx.put("yurref", IdGenerate.getIdStr(30));
        body.put("ntdmaaddx", Collections.singletonList(ntdmaaddx));

        Map<String, String> ntbusmody = new HashMap(1);
        // 业务模式
        ntbusmody.put("busmod",configDTO.getBusmod());
        body.put("ntbusmody", Collections.singletonList(ntbusmody));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMAADD", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();

        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            JSONObject data = JSON.parseObject(asResult.getData().toString());
            //创建成功Body为空，可直接返回
            return AR.success(data);
        }
        return AR.fail(asResult.getMsg());
    }

    public static String subAccountCreateResult(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        AR<JSONObject> result = subAccountCreate(cashSubAccount, configDTO);
        if(result.isSuccess()) {
            JSONObject data = result.getData();
            if(Objects.isNull(data)){
                log.error("subAccountCreateResult data is null");
                return "";
            }
            JSONArray ntdmabadz1 = data.getJSONArray("ntdmabadz1");
            if(Objects.isNull(ntdmabadz1) || ntdmabadz1.isEmpty()){
                log.error("subAccountCreateResult ntdmabadz1 is null");
                return "";
            }

            JSONObject detailInfo = ntdmabadz1.getJSONObject(0);
            String rtnsts = detailInfo.getString("rtnsts");
            if("S".equals(rtnsts)){
                return  detailInfo.getString("dmanbr");
            }
        }
        return "";
    }

    public static AR<Boolean> subAccountCreateTest(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> body = new HashMap<>(2);
        Map<String, String> ntdmaaddx = new HashMap(8);
        //账号
        ntdmaaddx.put("accnbr", cashSubAccount.getBankAccount());
        //记账子单元编号 自定义记账子单元编号：非空 系统自动生成记账子单元编号：空
        ntdmaaddx.put("dmanbr", cashSubAccount.getSubAccount());
        //记账子单元名称
        ntdmaaddx.put("dmanam", cashSubAccount.getSubAccountName());
        //额度控制标志，Y：允许透支 N：不允许透支
        ntdmaaddx.put("ovrctl", "N");
        //退票处理方式，Y：退回原记账子单元 N：退回结算户
        ntdmaaddx.put("bcktyp", "Y");
        //业务参考号 客户保证唯一
        ntdmaaddx.put("yurref", IdGenerate.getIdStr(30));
        body.put("ntdmaaddx", Collections.singletonList(ntdmaaddx));

        Map<String, String> ntbusmody = new HashMap(1);
        // 业务模式
        ntbusmody.put("busmod",configDTO.getBusmod());
        body.put("ntbusmody", Collections.singletonList(ntbusmody));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMAADD", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();

        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            //创建成功Body为空，可直接返回
            return AR.success();
        }
        return AR.fail(asResult.getMsg());
    }

    /**
     * 删除单个记账子单元
     *
     * @param subAccount
     * @param configDTO
     * @return
     */
    public static AR<Object> subAccountDelete(String bankAccount, String subAccount,ConfigDTO configDTO) {
        ServiceSupport serviceSupport = new ServiceSupport(configDTO);
        Map<String, List> body = new HashMap<>(4);

        Map<String, String> ntbusmody = new HashMap(1);
        // 业务模式
        ntbusmody.put("busmod",configDTO.getBusmod());
        body.put("ntbusmody", Collections.singletonList(ntbusmody));

        Map<String, String> ntdmadltx1 = new HashMap(4);
        ntdmadltx1.put("accnbr", bankAccount);
        //业务参考号 客户保证唯一
        ntdmadltx1.put("yurref", IdGenerate.getIdStr(30));
        body.put("ntdmadltx1", Collections.singletonList(ntdmadltx1));

        Map<String, String> ntdmadltx2 = new HashMap(4);
        ntdmadltx2.put("dmanbr", subAccount);
        body.put("ntdmadltx2", Collections.singletonList(ntdmadltx2));

        CommonRequestParam dcdaccye = CommonRequestParam.builder()
                .head(ServiceSupport.getHeaders("NTDMADLT", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID))
                .body(body)
                .build();
        final JsonObject jsonObject = new JsonObject();

        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        return serviceSupport.doProcess(jsonObject);
    }

    /**
     * 删除单个记账子单元
     *
     * @param subAccount
     * @param configDTO
     * @return
     */
    public static boolean subAccountDeleteFlag(String bankAccount, String subAccount, ConfigDTO configDTO) {
        AR<Object> result = subAccountDelete(bankAccount, subAccount, configDTO);
        if (result.isSuccess()) {
            log.info("subAccountDeleteFlag bankAccount:{};subAccount:{}; data:{}",bankAccount,subAccount,result.getData().toString());
            JSONObject data = JSON.parseObject(result.getData().toString());

            if(Objects.isNull(data)){
                log.error("subAccountDeleteFlag data is null");
                return false;
            }

            JSONArray ntoprrtnz = data.getJSONArray("ntoprrtnz");
            if(Objects.isNull(ntoprrtnz) || ntoprrtnz.isEmpty()){
                log.error("subAccountDeleteFlag ntoprrtnz is null");
                return false;
            }

            JSONObject detailInfo = ntoprrtnz.getJSONObject(0);
            String reqsts = detailInfo.getString("reqsts");
            String rtnflg = detailInfo.getString("rtnflg");
            log.info("subAccountDeleteFlag bankAccount:{};subAccount:{};reqsts:{};rtnflg:{}",bankAccount,subAccount,reqsts,rtnflg);
            if("FIN".equals(reqsts) && "S".equals(rtnflg)){
                return true;
            }
        }
        return false;
    }

    /**
     * 删除单个记账子单元
     *
     * @param subAccount
     * @param configDTO
     * @return
     */
    public static AR<Boolean> subAccountDeleteTest(String bankAccount, String subAccount, ConfigDTO configDTO) {
        ServiceSupport serviceSupport = new ServiceSupport(configDTO);
        Map<String, List> body = new HashMap<>(4);

        Map<String, String> ntbusmody = new HashMap(1);
        // 业务模式
        ntbusmody.put("busmod",configDTO.getBusmod());
        body.put("ntbusmody", Collections.singletonList(ntbusmody));

        Map<String, String> ntdmadltx1 = new HashMap(4);
        ntdmadltx1.put("accnbr", bankAccount);
        //业务参考号 客户保证唯一
        ntdmadltx1.put("yurref", IdGenerate.getIdStr(30));
        body.put("ntdmadltx1", Collections.singletonList(ntdmadltx1));

        Map<String, String> ntdmadltx2 = new HashMap(4);
        ntdmadltx2.put("dmanbr", subAccount);
        body.put("ntdmadltx2", Collections.singletonList(ntdmadltx2));

        CommonRequestParam dcdaccye = CommonRequestParam.builder()
                .head(ServiceSupport.getHeaders("NTDMADLT", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID))
                .body(body)
                .build();
        final JsonObject jsonObject = new JsonObject();

        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            //创建成功Body为空，可直接返回
            return AR.success();
        }
        return AR.fail(asResult.getMsg());
    }


    /**
     * [修改]招商银行[记账子单元]
     * 交易管家(记账) > 3.修改记账子单元NTDMAMNT
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<Boolean> subAccountModify(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> params = new HashMap<>(1);
        Map<String, String> bb1paybmx1 = new HashMap(2);
        //分行号
        bb1paybmx1.put("bbknbr", cashSubAccount.getBankBranchNumber());
        //账号
        bb1paybmx1.put("accnbr", cashSubAccount.getBankAccount());
        //记账子单元编号
        bb1paybmx1.put("dmanbr", cashSubAccount.getSubAccount());
        //记账子单元名称
        bb1paybmx1.put("dmanam", cashSubAccount.getSubAccountName());
        //额度控制标志，Y：允许透支 N：不允许透支
        bb1paybmx1.put("ovrctl", "N");
        //退票处理方式，Y：退回原记账子单元 N：退回结算户
        bb1paybmx1.put("bcktyp", "Y");
        //余额非零时是否可关闭，Y：可关闭，N：不可关闭
        bb1paybmx1.put("clstyp", "N");

        params.put("ntdmamntx1", Collections.singletonList(bb1paybmx1));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMAMNT", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(params).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            ObjectMapper mapper = new ObjectMapper();
            log.info(asResult.getData().toString());
//            return AR.success(mapper.readValue(asResult.getData().toString(), PaymentSearchResult.class));
            return AR.success();
        }
        return AR.fail(asResult.getMsg());
    }

    /**
     * [查询]招商银行[记账子单元]
     * 交易管家(记账) > 4.查询记账子单元信息NTDMALST
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<JSONObject> subAccountQuery(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> body = new HashMap<>(1);
        Map<String, String> ntdmalstx = new HashMap(2);
        //账号
        ntdmalstx.put("accnbr", cashSubAccount.getBankAccount());
        //记账子单元编号
        ntdmalstx.put("dmanbr", cashSubAccount.getSubAccount());

        body.put("ntdmalstx", Collections.singletonList(ntdmalstx));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMALST", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);
        if (asResult.isSuccess()) {
            log.info("subAccountQuery:{}",asResult.getData().toString());
            JSONObject data = JSON.parseObject(asResult.getData().toString());
            return AR.success(data);
        }
        return AR.fail(asResult.getMsg());
    }

    public static boolean subAccountCloseFlag(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        AR<JSONObject> result = subAccountQuery(cashSubAccount, configDTO);
        return result.isSuccess() && MapUtils.isEmpty(result.getData());
    }

    /**
     * [查询]招商银行[记账子单元]
     * 交易管家(记账) > 4.查询记账子单元信息NTDMALST
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<Boolean> subAccountQueryTest(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> body = new HashMap<>(1);
        Map<String, String> ntdmalstx = new HashMap(2);
        //账号
        ntdmalstx.put("accnbr", cashSubAccount.getBankAccount());
        //记账子单元编号
        ntdmalstx.put("dmanbr", cashSubAccount.getSubAccount());

        body.put("ntdmalstx", Collections.singletonList(ntdmalstx));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMALST", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            ObjectMapper mapper = new ObjectMapper();
            log.info(asResult.getData().toString());
            return AR.success(true);
        }
        return AR.fail(asResult.getMsg());
    }

/******************************* 余额与交易查询[开始] ************************************/

    /**
     * [查询]记账子单元[当天]交易
     * 交易管家(记账) > 14.查询记账子单元当天交易NTDMTLST
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<List<AccountTrade>> subAccountTradeToday(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);
        log.info("<<<<<查询的参数: serviceSupport--->{}", JSONObject.toJSONString(serviceSupport));
        Map<String, List> body = new HashMap<>(1);
        Map<String, String> ntdmtlsty = new HashMap(2);
        //账号
        ntdmtlsty.put("accnbr", cashSubAccount.getBankAccount());
        if (!CommonUtil.isEmpty(cashSubAccount.getSubAccount())) {
            //记账子单元编号
            ntdmtlsty.put("dmanbr", cashSubAccount.getSubAccount());
        }

        body.put("ntdmtlsty", Collections.singletonList(ntdmtlsty));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMTLST", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            final String searchData = asResult.getData().toString();
            if (CommonUtil.isEmpty(searchData) || CommonUtil.isJsonEmpty(searchData)) {
                return AR.success(Collections.emptyList());
            }
            ObjectMapper mapper = new ObjectMapper();
            List<AccountTrade> accountTrades = null;
            try {
                final String record = mapper.readTree(searchData).get("ntdmtlstz").toString();
                JavaType jt = mapper.getTypeFactory().constructParametricType(List.class, AccountTrade.class);
                accountTrades = mapper.readValue(record, jt);
            } catch (Exception e) {
                log.error("[查询]记账子单元[当天]交易，过程中解析JSON格式异常，异常：{}，Json数据为：{}", e.getMessage(), searchData);
                e.printStackTrace();
            }
            return AR.success(accountTrades);
        }
        return AR.fail(asResult.getMsg());
    }

    public static AR<List<AccountTrade>> subAccountTradeTodayTest(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);
        log.info("<<<<<查询的参数: serviceSupport--->{}", JSONObject.toJSONString(serviceSupport));
        Map<String, List> body = new HashMap<>(1);
        Map<String, String> ntdmtlsty = new HashMap(2);
        //账号
        ntdmtlsty.put("accnbr", cashSubAccount.getBankAccount());
        if (!CommonUtil.isEmpty(cashSubAccount.getSubAccount())) {
            //记账子单元编号
            ntdmtlsty.put("dmanbr", cashSubAccount.getSubAccount());
        }

        body.put("ntdmtlsty", Collections.singletonList(ntdmtlsty));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMTLST", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            final String searchData = asResult.getData().toString();
            if (CommonUtil.isEmpty(searchData) || CommonUtil.isJsonEmpty(searchData)) {
                return AR.success(Collections.emptyList());
            }
            ObjectMapper mapper = new ObjectMapper();
            List<AccountTrade> accountTrades = null;
            try {
                final String record = mapper.readTree(searchData).get("ntdmtlstz").toString();
                JavaType jt = mapper.getTypeFactory().constructParametricType(List.class, AccountTrade.class);
                accountTrades = mapper.readValue(record, jt);
            } catch (Exception e) {
                log.error("[查询]记账子单元[当天]交易，过程中解析JSON格式异常，异常：{}，Json数据为：{}", e.getMessage(), searchData);
                e.printStackTrace();
            }
            return AR.success(accountTrades);
        }
        return AR.fail(asResult.getMsg());
    }

    /**
     * [查询]记账子单元[当天]所有交易
     * 交易管家(记账) > 14.查询记账子单元当天交易NTDMTLST
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static List<AccountTrade> findAllAccountTradeToday(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        String ctnKey = null;
        List<AccountTrade> tradeList = new ArrayList<>();
        do {
            AR<AccountTradeToday> tradeTodayAR = findAccountTradeToday(cashSubAccount, ctnKey, configDTO);
            if (tradeTodayAR.isSuccess()) {
                AccountTradeToday accountTradeToday = tradeTodayAR.getData();
                if (!CommonUtil.isEmpty(accountTradeToday)) {
                    List<AccountTrade> accountTrades = accountTradeToday.getAccountTrades();
                    if (CommonUtil.isEmpty(accountTrades)) {
                        return tradeList;
                    }
                    tradeList.addAll(accountTrades);
                }
                List<AccountTradeResumeInfo> tradeResumeInfos = accountTradeToday.getTradeResumeInfo();
                if (tradeResumeInfos != null && tradeResumeInfos.size() > 0) {
                    ctnKey = tradeResumeInfos.get(0).getResumeFlagInfo();
                } else {
                    ctnKey = null;
                }
            } else {
                ctnKey = null;
                log.error("结算户：{}请求当日无交易失败:{}", cashSubAccount, tradeTodayAR);
            }
        } while (!StringUtils.isEmpty(ctnKey));
        return tradeList;
    }

    /**
     * [查询]记账子单元[当天]所有交易
     * 交易管家(记账) > 14.查询记账子单元当天交易NTDMTLST
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static List<AccountTrade> findAllAccountTradeTodayTest(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        String ctnKey = null;
        List<AccountTrade> tradeList = new ArrayList<>();
        do {
            AR<AccountTradeToday> tradeTodayAR = findAccountTradeToday(cashSubAccount, ctnKey, configDTO);
            if (tradeTodayAR.isSuccess()) {
                AccountTradeToday accountTradeToday = tradeTodayAR.getData();
                if (!CommonUtil.isEmpty(accountTradeToday)) {
                    List<AccountTrade> accountTrades = accountTradeToday.getAccountTrades();
                    if (CommonUtil.isEmpty(accountTrades)) {
                        return tradeList;
                    }
                    tradeList.addAll(accountTrades);
                }
                List<AccountTradeResumeInfo> tradeResumeInfos = accountTradeToday.getTradeResumeInfo();
                if (tradeResumeInfos != null && tradeResumeInfos.size() > 0) {
                    ctnKey = tradeResumeInfos.get(0).getResumeFlagInfo();
                } else {
                    ctnKey = null;
                }
            } else {
                ctnKey = null;
                log.error("结算户：{}请求当日无交易失败:{}", cashSubAccount, tradeTodayAR);
            }
        } while (!StringUtils.isEmpty(ctnKey));
        return tradeList;
    }

    /**
     * [查询]记账子单元[当天]交易
     * 交易管家(记账) > 14.查询记账子单元当天交易NTDMTLST
     *
     * @param cashSubAccount 子账号信息
     * @param ctnKey         续传字段
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<AccountTradeToday> findAccountTradeToday(CashSubAccount cashSubAccount, String ctnKey, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);
        log.info("<<<<<查询的参数: serviceSupport--->{}", JSONObject.toJSONString(serviceSupport));
        Map<String, List> params = new HashMap<>(1);
        Map<String, String> bb1paybmx1 = new HashMap(2);
        //账号
        bb1paybmx1.put("accnbr", cashSubAccount.getBankAccount());
        if (!CommonUtil.isEmpty(cashSubAccount.getSubAccount())) {
            //记账子单元编号
            bb1paybmx1.put("dmanbr", cashSubAccount.getSubAccount());
        }
        if (!StringUtils.isEmpty(ctnKey)) {
            //续传字段
            bb1paybmx1.put("ctnkey", ctnKey);
        }
        params.put("ntdmtlsty", Collections.singletonList(bb1paybmx1));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMTLST", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(params).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            log.info("findAccountTradeToday:{}",asResult.getData().toString());
            try {
                ObjectMapper mapper = new ObjectMapper();
                return AR.success(mapper.readValue(asResult.getData().toString(), AccountTradeToday.class));
            } catch (Exception e) {
                log.error("[查询]记账子单元[当天]交易，过程中解析JSON格式异常，异常：{}，Json数据为：{}", e.getMessage(), asResult.getData().toString());
                e.printStackTrace();
            }
        }
        return AR.fail(asResult.getMsg());
    }

    /**
     * [查询]记账子单元[历史]交易
     * 交易管家(记账) > 15.查询记账子单元历史交易NTDMTHLS
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<Boolean> subAccountTradeHistory(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> body = new HashMap<>(1);
        Map<String, String> ntdmthlsy = new HashMap(2);
        //账号
        ntdmthlsy.put("accnbr", cashSubAccount.getBankAccount());
        if (!CommonUtil.isEmpty(cashSubAccount.getSubAccount())) {
            //记账子单元编号
            ntdmthlsy.put("dmanbr", cashSubAccount.getSubAccount());
        }
        //起始日期，只能查询近 13 个月的历史交易
        ntdmthlsy.put("begdat", cashSubAccount.getBeginDate());
        //结束日期，小于当天，大于或等于起始日期，与起始日期相距100天内
        ntdmthlsy.put("enddat", cashSubAccount.getEndDate());

        body.put("ntdmthlsy", Collections.singletonList(ntdmthlsy));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMTHLS", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(body).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            ObjectMapper mapper = new ObjectMapper();
            log.info(asResult.getData().toString());
            return AR.success(true);
        }
        return AR.fail(asResult.getMsg());
    }


    /**
     * [查询]记账子单元[余额]
     * 交易管家(记账) > 16.查询记账子单元余额NTDMABAL
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<Boolean> subAccountBalance(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> params = new HashMap<>(1);
        Map<String, String> bb1paybmx1 = new HashMap(2);
        //账号
        bb1paybmx1.put("accnbr", cashSubAccount.getBankAccount());
        //记账子单元编号，填空表示查询该账号下所有记账子单元信息
        bb1paybmx1.put("dmanbr", cashSubAccount.getSubAccount());


        params.put("ntdmabalx", Collections.singletonList(bb1paybmx1));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMABAL", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(params).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            ObjectMapper mapper = new ObjectMapper();
            log.info("查询余额返回内容>>>：{}", asResult.getData().toString());
            return AR.success(true);
        }
        return AR.fail(asResult.getMsg());
    }

    /******************************* 余额与交易查询[结束] ************************************/

    /******************************* 交易管家(记账)的经办[开始] ************************************/
    /**
     * 记账子单元内部[转账]
     * 交易管家(记账) > 22.记账子单元内部转账NTDMATRX
     *
     * @param cashSubAccount 子账号信息
     * @param configDTO      招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<Boolean> subAccountTransfer(CashSubAccount cashSubAccount, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);

        Map<String, List> params = new HashMap<>(1);
        Map<String, String> bb1paybmx1 = new HashMap(2);
        //账号
        bb1paybmx1.put("accnbr", cashSubAccount.getBankAccount());
        //付款方记账子单元编号
        bb1paybmx1.put("dmadbt", cashSubAccount.getPaymentAccount());
        //收款方记账子单元编号
        bb1paybmx1.put("dmacrt", cashSubAccount.getAcceptAccount());
        //转账金额
        bb1paybmx1.put("trxamt", cashSubAccount.getAmount());
        //交易摘要
        bb1paybmx1.put("trxtxt", cashSubAccount.getTransRemark());


        params.put("ntdmatrxx1", Collections.singletonList(bb1paybmx1));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("NTDMATRX", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(params).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            ObjectMapper mapper = new ObjectMapper();
            log.info(asResult.getData().toString());
            return AR.success(true);
        }
        return AR.fail(asResult.getMsg());
    }

    /**
     * [查询]账务查询 账户交易信息查询全部
     * 账务查询 > 7.账户交易信息查询trsQryByBreakPoint
     *
     * @param normalAccountTradeQuery 账号信息
     * @param configDTO               招商连接信息
     * @return
     * @throws Exception
     */
    public static List<NormalAccountTrade> findNormalAccountTradeAll(NormalAccountTradeQuery normalAccountTradeQuery, ConfigDTO configDTO) {
        String queryAcctNbr = null;
        List<NormalAccountTradeResumeQueryInfo> normalAccountTradeResumeQueryInfos = null;
        List<NormalAccountTrade> tradeList = new ArrayList<>();
        do {
            AR<NormalAccountTradeInfo> trsQryByBreakPointAR = findNormalAccountTrade(normalAccountTradeQuery, queryAcctNbr, normalAccountTradeResumeQueryInfos, configDTO);
            if (trsQryByBreakPointAR.isSuccess()) {
                NormalAccountTradeInfo normalAccountTradeInfo = trsQryByBreakPointAR.getData();
                if (!CommonUtil.isEmpty(normalAccountTradeInfo)) {
                    List<NormalAccountTrade> accountTrades = normalAccountTradeInfo.getNormalAccountTrades();
                    if (CommonUtil.isEmpty(accountTrades)) {
                        return tradeList;
                    }
                    tradeList.addAll(accountTrades);
                }
                List<NormalAccountTradeResumeInfo> tradeResumeInfos = normalAccountTradeInfo.getNormalAccountTradeResumeInfos();
                if (tradeResumeInfos != null && tradeResumeInfos.size() > 0) {
                    NormalAccountTradeResumeInfo normalAccountTradeResumeInfo = tradeResumeInfos.get(0);
                    String ctnFlag = normalAccountTradeResumeInfo.getCtnFlag();
                    if ("Y".equals(ctnFlag)) {
                        queryAcctNbr = normalAccountTradeResumeInfo.getQueryAcctNbr();
                        normalAccountTradeResumeQueryInfos = normalAccountTradeInfo.getNormalAccountTradeResumeQueryInfos();
                    } else {
                        queryAcctNbr = null;
                        normalAccountTradeResumeQueryInfos = null;
                    }
                } else {
                    queryAcctNbr = null;
                    normalAccountTradeResumeQueryInfos = null;
                }
            } else {
                queryAcctNbr = null;
                normalAccountTradeResumeQueryInfos = null;
                log.error("结算户：{}请求当日无交易失败:{}", normalAccountTradeQuery, trsQryByBreakPointAR);
            }
        } while (!StringUtils.isEmpty(queryAcctNbr));
        return tradeList;
    }

    /**
     * [查询]账务查询 账户交易信息查询--只会200条
     * 账务查询 > 7.账户交易信息查询trsQryByBreakPoint
     *
     * @param normalAccountTradeQuery 查询的账号信息
     * @param configDTO               招商连接信息
     * @return
     * @throws Exception
     */
    public static AR<NormalAccountTradeInfo> findNormalAccountTrade(NormalAccountTradeQuery normalAccountTradeQuery, String queryAcctNbr, List<NormalAccountTradeResumeQueryInfo> normalAccountTradeResumeQueryInfos, ConfigDTO configDTO) {
        final ServiceSupport serviceSupport = new ServiceSupport(configDTO);
        Map<String, List> params = new HashMap<>(1);
        Map<String, String> transQueryByBreakPointX1 = new HashMap(2);
        //账号
        String cardNbr = normalAccountTradeQuery.getBankAccount();
        if (StringUtils.isEmpty(cardNbr)) {
            throw new RuntimeException("查询的账户不能为空");
        }
        transQueryByBreakPointX1.put("cardNbr", cardNbr);
        String beginDate = normalAccountTradeQuery.getBeginDate();
        if (StringUtils.isEmpty(beginDate)) {
            throw new RuntimeException("查询的账户的开始时间不能为空");
        }
        transQueryByBreakPointX1.put("beginDate", beginDate);
        String endDate = normalAccountTradeQuery.getEndDate();
        if (StringUtils.isEmpty(endDate)) {
            throw new RuntimeException("查询的账户的结束时间不能为空");
        }
        transQueryByBreakPointX1.put("endDate", endDate);
        //续传参数
        if (!StringUtils.isEmpty(queryAcctNbr)) {
            transQueryByBreakPointX1.put("queryAcctNbr", queryAcctNbr);
            if (normalAccountTradeResumeQueryInfos == null) {
                throw new RuntimeException("续传查询需要传入续传参数Y1");
            }
            params.put("TRANSQUERYBYBREAKPOINT_Y1", normalAccountTradeResumeQueryInfos);
        }
        String currencyCode = normalAccountTradeQuery.getCurrencyCode();
        //币种--没传默认人民币
        transQueryByBreakPointX1.put("currencyCode", StringUtils.isEmpty(currencyCode) ? "10" : currencyCode);
        params.put("TRANSQUERYBYBREAKPOINT_X1", Collections.singletonList(transQueryByBreakPointX1));
        final CommonRequestParam dcdaccye = CommonRequestParam.builder().head(ServiceSupport.getHeaders("trsQryByBreakPoint", ServiceSupport.getMillisTime() + RandomUtil.randomStringUpper(15), serviceSupport.UID)).body(params).build();

        final JsonObject jsonObject = new JsonObject();
        jsonObject.add("request", new Gson().toJsonTree(dcdaccye));
        final AR<Object> asResult = serviceSupport.doProcess(jsonObject);

        if (asResult.isSuccess()) {
            try {
                ObjectMapper mapper = new ObjectMapper();
                return AR.success(mapper.readValue(asResult.getData().toString(), NormalAccountTradeInfo.class));
            } catch (Exception e) {
                log.error("[查询]账务查询[当天]账户交易信息查询，过程中解析JSON格式异常，异常：{}，Json数据为：{}", e.getMessage(), asResult.getData().toString());
                e.printStackTrace();
            }
        }
        return AR.fail(asResult.getMsg());
    }
}
